#include <string.h>
#include "StringCreator.h"
#include <errno.h>
#include <stdio.h>

#define OUTSET "UTF-32"
#define INSET "UTF-8"

StringCreator StringCreator::SINGLETON;

natural char2uchar (const char * utf8, uchar** ret);

String StringCreator::operator*(const char* in)
{
	uchar* ret;
	int s = char2uchar(in, &ret);

	String r(ret, s);

	return r;
}

int utf8CharSize(char c)
{
	if((c & 128) == 0)
		return 1;

	if((c & 0xFE) == 0xFC)
		return 6;

	if((c & 0xFC) == 0xF8)
		return 5;

	if((c & 0xF8) == 0xF0)
		return 4;

	if((c & 0xF0) == 0xE0)
		return 3;

	if((c & 0xE0) == 0xC0)
		return 2;

	throw "Invalid UTF-8 String";
}

byte masks[] = {0, 0, 0x1F, 0x0F, 0x07, 0x03, 0x01};

uchar convert(char* utf8, int numChars)
{
	unsigned byte c = ((unsigned byte*)utf8)[0];

	if(numChars == 1)
		return c;

	c = c & masks[numChars];

	uchar r = c;

	for(int i = 1; i < numChars; i++)
	{
		c = (((unsigned byte*)utf8)[i]);
		c = c & 0x3F;
		uchar tmp = c;
		r = r << 6;
		r = r | tmp;
	}

	return r;
}

natural char2uchar (const char * in, uchar** ret)
{
	char * utf8 = (char*)(void*)in;

	if (utf8[0] == '\0')
	{
		*ret = (uchar*)(void*)L"";

		return 0;
	}

	size_t utf8len  = 0;
	size_t utf32len = 0;

	for(unsigned int i = 0; utf8[i] != '\0'; i++)
	{
		utf8len++;

		if((utf8[i] & 128) == 0 || (utf8[i] & 64) != 0)
			utf32len++;
	}

	uchar * utf32 = new uchar[utf32len];

	int j = 0;

	char* utf8tmp = utf8;

	for(unsigned int i = 0; utf8[i] != '\0'; )
	{
		int numChars = utf8CharSize(utf8[i]);

		utf32[j] = convert(utf8tmp, numChars);
		i += numChars;
		j++;
		utf8tmp += numChars;
	}

	*ret = utf32;

	return utf32len;
}

StringBufferCreator& StringCreator::operator*(){StringBufferCreator r; return r;}
